package com.asset.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.asset.common.BaseResponse;
import com.asset.common.ErrorCode;
import com.asset.common.ResultUtils;
import com.asset.constant.UserConstant;
import com.asset.exception.BusinessException;
import com.asset.exception.ThrowUtils;
import com.asset.manager.act.BudgetActManager;
import com.asset.model.dto.approval.BudgetApproveRequest;
import com.asset.model.dto.approval.budget.*;
import com.asset.model.entity.BudgetApplication;
import com.asset.model.entity.BudgetApplicationDetail;
import com.asset.model.entity.CascadeAssetCategory;
import com.asset.model.entity.User;
import com.asset.model.vo.LoginUserVO;
import com.asset.service.BudgetService;
import com.asset.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;

/**
 * 预算申请
 */
@Slf4j
@RestController
@RequestMapping("/budget")
public class BudgetController {
    @Resource
    private BudgetService budgetService;
    @Resource
    private UserService userService;
    @Resource
    private BudgetActManager budgetActManager;

    /**
     * 新增预算申请
     * 填写预算名称（必填）、费用信息（可不填）
     * 点击提交，申请状态为 "草稿"，进入详细填写页面
     * 费用在后面添加好资产后，再进行计算（预算总金额手填，计算是用来参考的
     * 申请公司id 、申请人id从 userLogin 获取
     * 表头：
     *      序号 - 预算名称 - 预算编号（id） - 预算费用 - 申请时间 - 申请公司 - 申请人 - 预算状态 - 审批流程状态 - 附件（下载） - 操作
     *
     * @param budgetAddRequest 预算申请请求
     * @param request
     * @return
     */
    @PostMapping("/add/addBudget")
    public BaseResponse<Boolean> addBudget(@RequestBody BudgetAddRequest budgetAddRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(budgetAddRequest == null, ErrorCode.PARAMS_ERROR);

        BudgetApplication budgetApplication = new BudgetApplication();
        BeanUtils.copyProperties(budgetAddRequest, budgetApplication);

        // 获取当前登录用户
        LoginUserVO loginUser = (LoginUserVO) StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        // 设置申请公司ID、申请人ID，需要从当前登录者设置
        budgetApplication.setCompanyId((int) loginUser.getCompanyId());
        budgetApplication.setApplicantId(loginUser.getId());
        budgetApplication.setStatus(1); // 刚新增的预算申请状态为 "草稿"

        // 插入数据库，启动流程
        boolean result = budgetService.addBudgetApplication(budgetApplication, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 提交预算申请，推进流程
     * 前端应校验是否为草稿状态，否则对应的详细页面没有提交按钮，也不能修改预算信息
     *
     * @param budgetSubmitRequest 提交的基本信息，包括预算申请ID和提交意见
     * @param request
     * @return
     */
    @PostMapping("/submit")
    public BaseResponse<Boolean> submitBudget(@RequestBody BudgetSubmitRequest budgetSubmitRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(budgetSubmitRequest == null, ErrorCode.PARAMS_ERROR);
        // 获取该预算申请id
        Integer budgetId = budgetSubmitRequest.getBudgetId();
        // 上报的信息
        String message = budgetSubmitRequest.getMessage();

        // 获取该条预算申请记录
        BudgetApplication budgetApplication = budgetService.getBudgetApplicationById(budgetId);

        ThrowUtils.throwIf(budgetApplication == null, ErrorCode.NOT_FOUND_ERROR);
        ThrowUtils.throwIf(budgetApplication.getStatus() != 1, ErrorCode.OPERATION_ERROR, "只能提交草稿状态的预算申请");

        LoginUserVO loginUser = (LoginUserVO) StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        // 这里只需要判断是否为该预算草稿的申请人，前后端都要校验，防止提交别人的申请（虽然说查询的时候只能看自己的）
        if (loginUser != null && (loginUser.getId() == budgetApplication.getApplicantId() || loginUser.getIsAdmin() == 1)) {
            String processInstanceId = budgetApplication.getWorkflowId();           // 获取流程实例ID
            String taskId = budgetActManager.getTask(loginUser, processInstanceId); // 获取预算流程申请人的当前任务ID
            Double totalAmount = budgetApplication.getTotalAmount();                // 获取预算金额
            // 提交信息，推进流程
            boolean r = budgetActManager.completeTask(taskId, processInstanceId, message,totalAmount, budgetId);
            if (r) {
                budgetApplication.setApprovalStatus("本公司领导审批中"); // 更改该预算的流程状态（未提交前是 "项目部填写预算申请"
                budgetApplication.setStatus(2);                       // 更改该预算的状态（未提交前是 "草稿"
                budgetApplication.setApplicationTime(new Date());     // 设置提交时间
                budgetService.updateBudget(budgetApplication);        // 更新记录
                // 测试任务信息
                budgetActManager.getUserCompletedTasks(loginUser,processInstanceId);
                return ResultUtils.success(r);
            }
            return ResultUtils.success(false);
        } else {
            // 前端应该校验，这里只是为了防止前端绕过校验，
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "您没有权限提交该预算申请");
        }
    }

    /**
     * 申请人添加一条预算资产
     * 预算申请ID 由前端提供
     * 添加表单参数：
     *      资产名称（必填） - 资产类别（级联选择） - 规格型号（必填） - 数量（必填） - 单价（必填） - 总价（必填）
     * 表头：
     *      序号 - 资产名称 - 资产类别 - 规格型号 - 数量 - 单价 - 总价 - 剩余数量 - 操作
     */
    @PostMapping("/addBudgetAsset")
    public BaseResponse<Boolean> addBudgetAsset(@RequestBody BudgetAssetAddRequest budgetAssetAddRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(budgetAssetAddRequest == null, ErrorCode.PARAMS_ERROR);
        BudgetApplicationDetail budgetApplicationDetail = new BudgetApplicationDetail();
        BeanUtils.copyProperties(budgetAssetAddRequest, budgetApplicationDetail);

        Integer remainingQuantity = budgetApplicationDetail.getQuantity();
        budgetApplicationDetail.setRemainingQuantity(remainingQuantity);
        log.info(budgetApplicationDetail.toString());

        // 插入数据
        boolean result = budgetService.addBudgetApplicationDetail(budgetApplicationDetail);
        return ResultUtils.success(result);
    }

    /**
     * 删除/撤销预算申请
     * 只有草稿状态的预算申请才能删除
     * 只有草稿状态的预算申请才能撤销
     */
    @PostMapping("/delBudget")
    public BaseResponse<Boolean> delBudgetApplication(Integer budgetApplicationId, HttpServletRequest request) {
        ThrowUtils.throwIf(budgetApplicationId == null, ErrorCode.PARAMS_ERROR);

//        Integer userId = (Integer) request.getSession().getAttribute("login_user");
        LoginUserVO loginUser = (LoginUserVO) StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        Integer userId = loginUser.getId();
        ThrowUtils.throwIf(userId == null, ErrorCode.NOT_LOGIN_ERROR);

        boolean r = budgetService.delBudgetApplication(budgetApplicationId, userId);
        return ResultUtils.success(r);
    }

    /**
     * 删除预算资产
     */
    @PostMapping("/delBudgetAsset")
    public BaseResponse<Boolean> deleteBudgetAsset(@RequestBody BudgetDelRequest budgetDelRequest) {
        ThrowUtils.throwIf(budgetDelRequest == null, ErrorCode.PARAMS_ERROR);

        boolean r =budgetService.delBudgetApplicationDetail(budgetDelRequest.getId());
        return ResultUtils.success(r);
    }

    /**
     * 预算申请修改
     * 只有草稿状态的预算申请才能修改
     * 只有草稿状态的预算申请才能修改
     */
    @PostMapping("/updateBudget")
    public BaseResponse<Boolean> updateBudgetApplication(@RequestBody BudgetUpdateRequest budgetUpdateRequest) {
        ThrowUtils.throwIf(budgetUpdateRequest == null, ErrorCode.PARAMS_ERROR);

        boolean r = budgetService.updateBudget(budgetUpdateRequest);
        return ResultUtils.success(r);
    }

    /**
     * 本公司领导预算审批
     */
    @PostMapping("/approve/leaderByOur")
    public BaseResponse<Boolean> approveBudget(@RequestBody BudgetApproveRequest budgetApproveRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(budgetApproveRequest == null, ErrorCode.PARAMS_ERROR);
        // 获取当前登录用户
        LoginUserVO loginUser = (LoginUserVO) StpUtil.getSession().get(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(loginUser.getIsAdmin() != 2, ErrorCode.OPERATION_ERROR, "只有部门领导才能审批");
        // 执行审批业务逻辑
        boolean result = budgetService.approveBudgetByLeader(budgetApproveRequest, loginUser);
        // 输出流程信息
        budgetActManager.getUserCompletedTasks(loginUser, budgetApproveRequest.getBudgetApplicationId().toString());
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(result);
    }

    /**
     * 分页获取预算申请列表
     *
     * @param budgetQuerRequest
     * @return
     */
    @PostMapping("/list/page")
    public BaseResponse<PageInfo<BudgetApplication>> listBudgetApplicationByPage(@RequestBody BudgetQuerRequest budgetQuerRequest) {
        ThrowUtils.throwIf(budgetQuerRequest == null, ErrorCode.PARAMS_ERROR);
        int current = budgetQuerRequest.getCurrent();
        int pageSize = budgetQuerRequest.getPageSize();

        PageHelper.startPage(current, pageSize);
        List<BudgetApplication> budgetApplicationList = budgetService.getBudgetApplicationList(budgetQuerRequest);
        PageInfo<BudgetApplication> budgetApplicationListPage = new PageInfo<>(budgetApplicationList);

        return ResultUtils.success(budgetApplicationListPage);
    }

    /**
     * 分页获取预算资产列表
     *
     * @param budgetAssetQuerRequest
     * @return
     */
    @PostMapping("/list/budgetAssetPage")
    public BaseResponse<PageInfo<BudgetApplicationDetail>> listBudgetAssetByPage(@RequestBody BudgetAssetQuerRequest budgetAssetQuerRequest) {
        ThrowUtils.throwIf(budgetAssetQuerRequest == null, ErrorCode.PARAMS_ERROR);
        int current = budgetAssetQuerRequest.getCurrent();
        int pageSize = budgetAssetQuerRequest.getPageSize();

        PageHelper.startPage(current, pageSize);
        List<BudgetApplicationDetail> budgetDetails = budgetService.getBudgetDetailQueryWrapper(budgetAssetQuerRequest);
        if (budgetDetails.size() == 0 || budgetDetails == null) {
            return ResultUtils.error(ErrorCode.NOT_FOUND_ERROR, "未查询到该预算申请的资产信息");
        }
        PageInfo<BudgetApplicationDetail> budgetDetailPage = new PageInfo<>(budgetDetails);
        return ResultUtils.success(budgetDetailPage);
    }

    /**
     * 获取所有资产类别（三级联动
     * 前端用级联选择器
     */
    @PostMapping("/list/getAssetCategoryList")
    public BaseResponse<List<CascadeAssetCategory>> listAssetCategory() {
        List<CascadeAssetCategory> assetCategoryList = budgetService.getCascadeAssetCategoryList();
        return ResultUtils.success(assetCategoryList);
    }

    // 获取预算流程信息
}
